# node.js读取文件,添加依赖

var fs = require('fs');
var path = require('path');

//解析需要遍历的文件夹
var filePath = path.resolve('./pages');

//调用文件遍历方法
fileDisplay(filePath);

/**
 * 文件遍历方法
 * @param filePath 需要遍历的文件路径
 */
function fileDisplay(filePath) {
    //根据文件路径读取文件,返回文件列表
    fs.readdir(filePath, function (err, files) {
        if (err) {
            console.warn(err)
        } else {
            //遍历读取到的文件列表
            files.forEach(function (filename) {
                //获取当前文件的绝对路径
                var filedir = path.join(filePath, filename);
                //根据文件路径获取文件信息,返回一个fs.Stats对象
                fs.stat(filedir, function (eror, stats) {
                    if (eror) {
                        console.warn('获取文件stats失败');
                    } else {
                        var isFile = stats.isFile();// 是文件
                        var isDir = stats.isDirectory();// 是文件夹
                        if (isFile && path.extname(filedir) === '.js') {
                            readJsFile(filedir, filename)
                        }
                        if (isDir) {
                            fileDisplay(filedir);//递归,如果是文件夹,就继续遍历该文件夹下面的文件
                        }
                    }
                })
            });
        }
    });
}

/**
 * 读取js文件 找到依赖
 * @param {*} filedir 
 * @param {*} filename 
 */
function readJsFile(filedir, filename) {
    fs.readFile(filedir, 'utf-8', (err, data) => {
        if (err) {
            console.error(err);
        } else {
            // 找到文件中需要添加的依赖
            const depsTemp = data.match(/(B)((\.[a-zA-Z.]+){2,})/g)
            // const depsTemp = data.match(/(B|SF|SFX)((\.[a-zA-Z.]+){2,})/g)
            let deps = []
            let depMap = new Set()
            for (let key in depsTemp) {
                const dep = depsTemp[key].replace('new ', '').replace('(', '')
                if (!depMap.has(dep) &&             // 去重
                    !dep.includes(filename.replace('.js', '')) &&          // 自己不需要写入依赖
                    !dep.includes('.call') &&           // call调用的
                    !dep.includes('.apply') &&          // apply调用的
                    !dep.includes('.prototype.')
                    // !dep.includes('SF.core.') &&
                    // !inWhiteList(dep) &&
                ) {
                    depMap.add(dep)
                    deps.push(dep)
                }
            }
            // 写入deps
            const depsDir = filedir.replace('.js', '.deps')
            readDepsFile(depsDir, deps)
        }
    });
}

/**
 * 白名单 是这里的就不需要添加
 * @param {*} dep 
 */
function inWhiteList (dep) {
    return [
        'SF.core.register',
        'SF.form.Form',
        'SF.form.JsonField',
        'SF.form.FormWindow',
        'SF.Ajax.jsonRequest',
        'SF.Ajax.abort',
        'SF.Ajax.request',
        'SF.util.IntervalTask',
        'SFX.viewport.init'
    ].findIndex(item => {
        return item === dep
    }) > -1
}

/**
 * 读取deps文件
 * @param {*} depsDir 
 * @param {*} deps 
 */
function readDepsFile(depsDir, deps) {
    fs.readFile(depsDir, 'utf-8', (err, data) => {
        if (err) {
            // 没有依赖文件 直接全部写入
            deps.forEach(dep => {
                writeDeps(depsDir, dep)
            })
        } else {
            // 有依赖文件,找没有的依赖加上去
            const oldDeps = data.split('\r\n')
            deps.forEach(dep => {
                const findIndex = oldDeps.findIndex(old => {
                    return old === dep
                })
                if (findIndex === -1) {
                    writeDeps(depsDir, dep)
                }
            })
        }
    });
}

/**
 * 写入 增加换行符及添加记录
 * @param {*} dir 
 * @param {*} content 
 */
function writeDeps (dir, content) {
    fs.appendFileSync(dir, `\r\n${content}`)
    // 添加记录
    fs.appendFileSync('E:\\test deps\\deps.txt', `\r\n${dir}: ${content}`)
}